<?
/*
 *  GGB - Gelin's Guest Book.
 *  Copyright (C) 2006  Denis Nelubin aka Gelin
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  http://gelin.ru
 *  mailto:den@gelin.ru
 *
 *  Description:    Provides checking for ban activity.
 *
 *  History:
 *  2007-01-20  Gelin   Initially created.
 *
 */

/**
 *  Provides checking for ban activity.
 */
class BanChecker {

    /** constructor */
    /*
    function BanChecker() {
    }
    */

    /**
     *  Returns array of request headers which should be checked for ban
     *  (and saved to database with message) and which are set in current request.
     *  @return array (map) of header name ($_SERVER key) to header value
     */
    function getRequestHeaders() {
        global $config;
        $result = array();
        foreach ($config['check_header'] as $key => $value) {
            if (isset($_SERVER[$key])) {
                $result[$key]['header_id'] = $key;
                $result[$key]['value'] = $this->prepareHeader($_SERVER[$key]);
            }
        }
        return $result;
    }

    /**
     *  Extracts headers of specified message from database.
     *  @param  $messageID  ID of a message
     *  @return array of headers
     */
    function getMessageHeaders($messageID) {
        global $storage;
        $headers = $storage->getMessageHeaders($messageID);
        $headers = $this->formatHeaders($headers);
        return $headers;
    }

    /**
     *  Checks headers if they are banned.
     *  @param  $headers    headers for check
     *  @return TRUE if access is allowed, FALSE if access is denied
     */
    function checkForBan($headers) {
        global $storage;
        $result = TRUE;
        $dbRules = array();
        //get appliable ban rules
        foreach ($headers as $key => $header) {
            $dbRules[$key] = $storage->getBanRule($header);
        }
        //get common list of rules
        $rules = array();
        foreach ($dbRules as $ruleset) {
            foreach ($ruleset as $rule) {
                $rules[$rule['id']] = $rule;
            }
        }
        //set of request headers should be greater or equal to set of rule headers
        //set of rule headers should be not greater than set of request headers.
        $requestSet = array_keys($headers);
        foreach ($rules as $rule) {
            $ruleSet = array_keys($rule['headers']);
            $diff = array_diff($ruleSet, $requestSet);  //set substraction
            if (count($diff) == 0) {    //rule is applicable
                $result = FALSE;    //found rule which denies access
                break;
            }
        }
        return $result;
    }

    /**
     *  Formats headers. Adds hostname for headers with IP address. Adds labels for headers.
     *  @param  $headers    array of headers
     *  @return formatted headers
     */
    function formatHeaders($headers) {
        global $config;
        //add hostnames
        if (isset($headers['REMOTE_ADDR'])) {
            $headers['REMOTE_ADDR']['is_ip'] = TRUE;
            $headers['REMOTE_ADDR']['host_value'] = $this->getHostName($headers['REMOTE_ADDR']['value']);
        }
        if (isset($headers['HTTP_X_FORWARDED_FOR'])) {
            $headers['HTTP_X_FORWARDED_FOR']['is_ip'] = TRUE;
            $headers['HTTP_X_FORWARDED_FOR']['host_value'] = $this->getHostName($headers['HTTP_X_FORWARDED_FOR']['value']);
        }
        //add labels
        foreach ($headers as $key => $value) {
            $headers[$key]['label'] = $config['check_header'][$key]['label'];
        }
        return $headers;
    }

    /**
     *  Prepares header to be inserted to database.
     *  @param  $value  header value
     *  @return prepared value
     */
    function prepareHeader($value) {
        return substr(trim($value), 0, 255);
    }

    /**
     *  Tries to get host name from IP address.
     */
    function getHostName($ip) {
        global $config;
        if ($config['behaviour']['immediate_dns']) {
            return @gethostbyaddr($ip);
        } else {
            return NULL;
        }
    }

}

?>